Skip to content
标签
spring
字数
5321 字
阅读时间
25 分钟

一、spring框架介绍

spring用来管理javabean的框架,可以理解spring就是粘合剂,他可以将各个框架整合起来是分层的JAVAEE 轻量级的开源框架

好处:

  • 解耦:程序员不需要创建管理对象,解除了对象管理和程序员之间的耦合
  • AOP编程支持:spring支持面向切面编程,可以方便对程序进行拦截和监控
  • 声明式事务:通过配置完成事务的管理,无需手动编程
  • 方便程序的测试:spring支持junit4,完成程序测试
  • 方便集成各个优秀的框架:mybatis ....
  • 降低javaeeapi的使用:spring将难用的api进行封装。

核心功能:

IoC/DI 控制反转/依赖注入

AOP 面向切面编程

声明式事务.

二、SSM环境搭建

2.1. pom文件

xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.yh</groupId>
	<artifactId>yh-parent</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>
	<!-- 集中定义依赖版本号 -->
	<properties>
		<junit.version>4.12</junit.version>
		<spring.version>4.2.4.RELEASE</spring.version>
		<mybatis.version>3.2.8</mybatis.version>
		<mybatis.spring.version>1.2.2</mybatis.spring.version>
		<mybatis.paginator.version>1.2.15</mybatis.paginator.version>
		<mysql.version>5.1.32</mysql.version>
		<slf4j.version>1.6.4</slf4j.version>
		<jackson.version>2.4.2</jackson.version>
		<druid.version>1.0.9</druid.version>
		<httpclient.version>4.3.5</httpclient.version>
		<jstl.version>1.2</jstl.version>
		<servlet-api.version>2.5</servlet-api.version>
		<jsp-api.version>2.0</jsp-api.version>
		<joda-time.version>2.5</joda-time.version>
		<commons-lang3.version>3.3.2</commons-lang3.version>
		<commons-io.version>1.3.2</commons-io.version>
		<commons-net.version>3.3</commons-net.version>
		<pagehelper.version>3.7.5</pagehelper.version>
		<jsqlparser.version>0.9.1</jsqlparser.version>
		<commons-fileupload.version>1.3.1</commons-fileupload.version>
		<jedis.version>2.7.2</jedis.version>
		<solrj.version>4.10.3</solrj.version>
		<dubbo.version>2.5.3</dubbo.version>
		<zookeeper.version>3.4.7</zookeeper.version>
		<zkclient.version>0.1</zkclient.version>
		<activemq.version>5.11.2</activemq.version>
		<freemarker.version>2.3.23</freemarker.version>
		<quartz.version>2.2.2</quartz.version>
	</properties>
	<dependencyManagement>
		<dependencies>
			<!-- 时间操作组件 -->
			<dependency>
				<groupId>joda-time</groupId>
				<artifactId>joda-time</artifactId>
				<version>${joda-time.version}</version>
			</dependency>
			<!-- Apache工具组件 -->
			<dependency>
				<groupId>org.apache.commons</groupId>
				<artifactId>commons-lang3</artifactId>
				<version>${commons-lang3.version}</version>
			</dependency>
			<dependency>
				<groupId>org.apache.commons</groupId>
				<artifactId>commons-io</artifactId>
				<version>${commons-io.version}</version>
			</dependency>
			<dependency>
				<groupId>commons-net</groupId>
				<artifactId>commons-net</artifactId>
				<version>${commons-net.version}</version>
			</dependency>
			<!-- Jackson Json处理工具包 -->
			<dependency>
				<groupId>com.fasterxml.jackson.core</groupId>
				<artifactId>jackson-databind</artifactId>
				<version>${jackson.version}</version>
			</dependency>
			<!-- httpclient -->
			<dependency>
				<groupId>org.apache.httpcomponents</groupId>
				<artifactId>httpclient</artifactId>
				<version>${httpclient.version}</version>
			</dependency>
			<!-- quartz任务调度框架 -->
			<dependency>
				<groupId>org.quartz-scheduler</groupId>
				<artifactId>quartz</artifactId>
				<version>${quartz.version}</version>
			</dependency>
			<!-- 单元测试 -->
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>
			<!-- 日志处理 -->
			<dependency>
				<groupId>org.slf4j</groupId>
				<artifactId>slf4j-log4j12</artifactId>
				<version>${slf4j.version}</version>
			</dependency>
			<!-- Mybatis -->
			<dependency>
				<groupId>org.mybatis</groupId>
				<artifactId>mybatis</artifactId>
				<version>${mybatis.version}</version>
			</dependency>
			<dependency>
				<groupId>org.mybatis</groupId>
				<artifactId>mybatis-spring</artifactId>
				<version>${mybatis.spring.version}</version>
			</dependency>
			<dependency>
				<groupId>com.github.miemiedev</groupId>
				<artifactId>mybatis-paginator</artifactId>
				<version>${mybatis.paginator.version}</version>
			</dependency>
			<dependency>
				<groupId>com.github.pagehelper</groupId>
				<artifactId>pagehelper</artifactId>
				<version>${pagehelper.version}</version>
			</dependency>
			<!-- MySql -->
			<dependency>
				<groupId>mysql</groupId>
				<artifactId>mysql-connector-java</artifactId>
				<version>${mysql.version}</version>
			</dependency>
			<!-- 连接池 -->
			<dependency>
				<groupId>com.alibaba</groupId>
				<artifactId>druid</artifactId>
				<version>${druid.version}</version>
			</dependency>
			<!-- Spring -->
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-context</artifactId>
				<version>${spring.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-beans</artifactId>
				<version>${spring.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-webmvc</artifactId>
				<version>${spring.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-jdbc</artifactId>
				<version>${spring.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-aspects</artifactId>
				<version>${spring.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-jms</artifactId>
				<version>${spring.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-context-support</artifactId>
				<version>${spring.version}</version>
			</dependency>
			<!-- JSP相关 -->
			<dependency>
				<groupId>jstl</groupId>
				<artifactId>jstl</artifactId>
				<version>${jstl.version}</version>
			</dependency>
			<dependency>
				<groupId>javax.servlet</groupId>
				<artifactId>servlet-api</artifactId>
				<version>${servlet-api.version}</version>
				<scope>provided</scope>
			</dependency>
			<dependency>
				<groupId>javax.servlet</groupId>
				<artifactId>jsp-api</artifactId>
				<version>${jsp-api.version}</version>
				<scope>provided</scope>
			</dependency>
			<!-- 文件上传组件 -->
			<dependency>
				<groupId>commons-fileupload</groupId>
				<artifactId>commons-fileupload</artifactId>
				<version>${commons-fileupload.version}</version>
			</dependency>
			<!-- Redis客户端 -->
			<dependency>
				<groupId>redis.clients</groupId>
				<artifactId>jedis</artifactId>
				<version>${jedis.version}</version>
			</dependency>
			<!-- solr客户端 -->
			<dependency>
				<groupId>org.apache.solr</groupId>
				<artifactId>solr-solrj</artifactId>
				<version>${solrj.version}</version>
			</dependency>
			<!-- dubbo相关 -->
			<dependency>
				<groupId>com.alibaba</groupId>
				<artifactId>dubbo</artifactId>
				<version>${dubbo.version}</version>
			</dependency>
			<dependency>
				<groupId>org.apache.zookeeper</groupId>
				<artifactId>zookeeper</artifactId>
				<version>${zookeeper.version}</version>
			</dependency>
			<dependency>
				<groupId>com.github.sgroschupf</groupId>
				<artifactId>zkclient</artifactId>
				<version>${zkclient.version}</version>
			</dependency>
			<dependency>
				<groupId>org.apache.activemq</groupId>
				<artifactId>activemq-all</artifactId>
				<version>${activemq.version}</version>
			</dependency>
			<dependency>
				<groupId>org.freemarker</groupId>
				<artifactId>freemarker</artifactId>
				<version>${freemarker.version}</version>
			</dependency>

		</dependencies>
	</dependencyManagement>

	<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<!-- 资源文件拷贝插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.7</version>
				<configuration>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
			<!-- java编译插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
		<pluginManagement>
			<plugins>
				<!-- 配置Tomcat插件 -->
				<plugin>
					<groupId>org.apache.tomcat.maven</groupId>
					<artifactId>tomcat7-maven-plugin</artifactId>
					<version>2.2</version>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

spring模块

testspring 提供测试功能
Core Container核心容器.Spring 启动最基本的条件.
BeansSpring 负责创建类对象并管理对象
Core核心类
Context上下文参数.获取外部资源或这管理注解等
SpElexpression.jar
AOP实现 aop 功能需要依赖
Aspects切面 AOP 依赖的包
Data Access/Integrationspring 封装数据访问层相关内容
JDBCSpring 对 JDBC 封装后的代码.
ORM封装了持久层框架的代码.例如 Hibernate
transactions对应 spring-tx.jar,声明式事务使用.
WEB需要 spring 完成 web 相关功能时需要.

2.2 配置文件

sqlMapConfig

xml
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEconfiguration
		PUBLIC"-//mybatis.org//DTD Config 3.0//EN"
		"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

</configuration>

dao层配置

db.properties 数据库连接信息

properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/hg?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

applicationContext-dao.xml

xml
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

	<!-- 数据库连接池 -->
	<!-- 加载配置文件 -->
	<context:property-placeholderlocation="classpath:properties/*.properties"/>
	<!-- 数据库连接池 -->
	<beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"
		destroy-method="close">
		<propertyname="url"value="${jdbc.url}"/>
		<propertyname="username"value="${jdbc.username}"/>
		<propertyname="password"value="${jdbc.password}"/>
		<propertyname="driverClassName"value="${jdbc.driver}"/>
		<propertyname="maxActive"value="10"/>
		<propertyname="minIdle"value="5"/>
	</bean>
	<!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
	<beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 数据库连接池 -->
		<propertyname="dataSource"ref="dataSource"/>
		<!-- 加载mybatis的全局配置文件 -->
		<propertyname="configLocation"value="classpath:mybatis/SqlMapConfig.xml"/>
	</bean>
	<beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<propertyname="basePackage"value="com.hg.mapper"/>
	</bean>
</beans>

Service层

applicationContext-service.xml

xml
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

	<!-- 包扫描器,扫描带@Service注解的类 -->
	<context:component-scan base-package="com.hg.service"></context:component-scan>
	
</beans>

applicationContext-trans.xml

xml
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	<!-- 事务管理器 -->
	<beanid="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 数据源 -->
		<propertyname="dataSource"ref="dataSource"/>
	</bean>
    <!-- 开启事务注解驱动 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
	<!-- 通知 -->
	<tx:adviceid="txAdvice"transaction-manager="transactionManager">
		<tx:attributes>
			<!-- 传播行为 -->
			<tx:methodname="save*"propagation="REQUIRED"/>
			<tx:methodname="insert*"propagation="REQUIRED"/>
			<tx:methodname="add*"propagation="REQUIRED"/>
			<tx:methodname="create*"propagation="REQUIRED"/>
			<tx:methodname="delete*"propagation="REQUIRED"/>
			<tx:methodname="update*"propagation="REQUIRED"/>
			<tx:methodname="find*"propagation="SUPPORTS"read-only="true"/>
			<tx:methodname="select*"propagation="SUPPORTS"read-only="true"/>
			<tx:methodname="get*"propagation="SUPPORTS"read-only="true"/>
		</tx:attributes>
	</tx:advice>
	<!-- 切面 -->
	<aop:config>
		<aop:advisoradvice-ref="txAdvice"
			pointcut="execution(* com.hg.service.*.*(..))"/>
	</aop:config>
</beans>

REQUIRED 如果有事务,就在当前事务里执行,没有则开启新事务。必须在事务中执行。SUPPORTS当前有事务就在当前事务中执行,没有则不开启事务

controller层

配置springmvc

xml
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 配置包扫描器 -->
<context:component-scan base-package="com.hg.controller"></context:component-scan>
<!-- 配置注解驱动 -->
<mvc:annotation-driven/>
<!-- 视图解析器 -->
<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix"value="/WEB-INF/jsp/"/>
		<property name="suffix"value=".jsp"/>
	</bean>
</beans>

web.xml

xml
<?xmlversion="1.0"encoding="UTF-8"?>
<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="hg"version="2.5">
	<display-name>hg-manager</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	<!-- 初始化spring容器 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring/applicationContext-*.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- 解决post乱码 -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


	<!-- springmvc的前端控制器 -->
	<servlet>
		<servlet-name>hg-manager</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring/springmvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>hg-manager</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

<load-on-startup>1</load-on-startup>初始化tomcat web容器时,即初始化spring容器。否则第一次访问时才初始化。

<url-pattern>/</url-pattern>静态资源会被拦截。

三、基础知识

3.1 spring创建对象

xml
<!-- 创建对象并赋值 -->
<!-- 
id:表示获取到对象的标识
class:创建哪个类的对象(全路径)
作用域
	singleton:默认值  一个bean对应一个实例对象
	prototype:一个bean对应多个实例对象
	request:在一个请求中,一个bean定义对应一个实例
	session: 在一个http session中,一个bean对应一个实例
	qlobal session:在一个全局http session中,一个bean对应一个实例
	request session qlobal session 旨在web的配置文件中有效
bean的生命周期
首先在类中创建初始化和销毁方法,然后在配置时添加init-method和destory-method方法
-->
<bean id="" class="" init-method="init初始化方法" destroy-method="destory销毁方法">
    <!-- 为构造方法中的参数赋值 -->
	<constructor-arg index="0" name="id" type="int" value="123"></constructor-arg>
</bean>

<!-- 通过实例工厂创建对象 -->
<bean id="factory"class="com.bjsxt.pojo.PeopleFactory"></bean>
<!-- 
 factory-bean:工厂类
 factory-method:工厂类中的方法名
-->
<bean id="peo1" factory-bean="factory" factory-method="newInstance"></bean>

<!-- 通过静态工厂创建对象 -->
<bean id="peo2" class="com.bjsxt.pojo.PeopleFactory" factory-method="newInstance"></bean>


<!-- 对象赋值 -->
<!-- 通过构造方法注入 -->
<bean id="peo" class="com.bjsxt.pojo.People"> 
    <!-- 为构造方法中的参数赋值 -->
	<constructor-arg index="0" name="id" type="int" value="123"></constructor-arg>
</bean>

<!-- 通过属性set方法注入 -->
<!--如果属性是基本数据类型或 String 等简单-->
<bean id="peo" class="com.bjsxt.pojo.People"> 
    <property name="id" value="222"></property> 
    <property name="name" value="张三"></property> 
</bean>
<!--等效于-->
<bean id="peo" class="com.bjsxt.pojo.People"> 
    <property name="id">
        <value>456</value> 
    </property> 
    <property name="name">
        <value>zhangsan</value> 
    </property> 
</bean>
<!--set-->
<property name="sets"> 
    <set> 
        <value>1</value>
        <value>2</value> 
        <value>3</value> 
        <value>4</value> 
    </set> 
</property>
<!--list-->
<property name="list"> 
    <list> 
        <value>1</value>
        <value>2</value> 
        <value>3</value> 
    </list> 
</property>
<!--list中只有一个值时-->
<property name="list" value="1"> </property>

<property name="strs" > 
    <array> 
        <value>1</value> 
        <value>2</value>
        <value>3</value> 
    </array> 
</property>
<!--map-->
<property name="map"> 
    <map> 
        <entry key="a" value="b" > 
        </entry> <entry key="c" value="d" > 
        </entry> 
    </map> 
</property>
<!--Properties-->
<property name="demo"> 
    <props> 
        <prop key="key">value</prop>
        <prop key="key1">value1</prop> 
    </props> 
</property>
<!--P命名空间-->
<!-- 首先声明p命名空间,即添加 xmlns:p="http://www.springframework.org/schema/p" -->
<bean id="" class="" p:属性名="基本数据类型" p:属性名-ref="对象类型"></bean>

<!--对象类型,依赖注入,将一个实例对象作为另一个对象的参数-->
<bean id="peo" class="com.bjsxt.pojo.People"> 
    <property name="desk" ref="desk"></property> 
</bean>
<bean id="desk" class="com.bjsxt.pojo.Desk"> 
    <property name="id" value="1"></property> 
    <property name="price" value="12"></property> 
</bean>

3.2 类后置处理器(对所有类增强)

java
package com.note.technology.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @Classname BeanPostProcessorDemo
 * @Description 对所有类增强的方法
 */
@Component
public class BeanPostProcessorDemo implements BeanPostProcessor {


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
}

3.3 获取spring中的对象

java
// BeanFactory和ApplicationContext区别:
// app是bean的子接口,加载配置文件所用的方法不同,bean可以实现延迟加载,app不能
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
People people = ac.getBean("peo",People.class); 
System.out.println(people);

3.4 AOP

  • 概念

    在原有纵向执行流程中添加横切面 ,不需要修改原有程序代码 ,具有高扩展性。

    连接点目标对象中所有可以被增强的方法
    原有功能切点, pointcut
    通知增强的功能的方法
    前置通知: 在切点之前执行的功能.before advice
    后置通知: 在切点之后执行的功能,after advice
    如果切点执行过程中出现异常,会触发异常通知.throws advice
    目标对象被代理的对象
    切面.所有功能总称
    织入把切面嵌入到原有功能的过程
    代理将通知织入到目标对象,行城的就是代理对象
  • Schema-based实现AOP

    java
    // 创建前置通知类
    public class MyBeforeAdvice implements MethodBeforeAdvice { 
        //arg0: 切点方法对象 Method 对象
        //arg1: 切点方法参数
        //arg2:切点在哪个对象中
        @Override 
        public void before(Method arg0, Object[] arg1, Objectarg2) throws Throwable { 
            System.out.println("执行前置通知"); 
        } 
    }
    
    // 创建后置通知类
    public class MyAfterAdvice implements AfterReturningAdvice { 
        //arg0: 切点方法返回值
        //arg1:切点方法对象
        //arg2:切点方法参数
        //arg3:切点方法所在类的对象
        @Override 
        public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { 
            System.out.println("执行后置通知");
        } 
    }
    
    // 创建异常通知类
    //新建一个类实现 throwsAdvice 接口
    //必须自己写方法,且必须叫 afterThrowing
    //有两种参数方式 必须是 1 个或 4 个异常类型要与切点报的异常类型一致
    public class MyThrow implements ThrowsAdvice{ 
        // public void afterThrowing(Method m, Object[] args, Object target, Exception ex) {
        // System.out.println("执行异常通知"); 
        // }
        public void afterThrowing(Exception ex) throws Throwable { 
            System.out.println("执行异常通过-schema-base 方式 "); 
        } 
    }
    
    // 创建环绕通知类
    public class MyArround implements MethodInterceptor { 
        @Override 
        public Object invoke(MethodInvocation arg0) throws Throwable { 
            System.out.println("环绕-前置");
            Object result = arg0.proceed();
            //放行,调用切点方式
            System.out.println("环绕-后置"); 
            return result; 
        } 
    }
    xml
    <!-- Schema-based方式通知配置 --> 
    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/sc hema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop. xsd">
        <!-- 配置通知类对象,在切面中引入 --> 
        <bean id="mybefore" class="com.bjsxt.advice.MyBeforeAdvice"></bean>
        <bean id="myafter" class="com.bjsxt.advice.MyAfterAdvice"></bean> 
        <bean id="mythrow" class="com.bjsxt.advice.MyThrow"></bean>
        <bean id="myarround" class="com.bjsxt.advice.MyArround"></bean>
        <!-- 配置切面 --> 
        <aop:config> 
            <!-- 配置切点 --> 
             <!-- * 通配符,匹配任意方法名,任意类名,任意一级包名 如果希望匹配任意方法参数 (..) --> 
            <aop:pointcut expression="execution(* com.bjsxt.test.Demo.demo2())" id="mypoint"/> 
            <!-- 通知 --> 
            <aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/> 
            <aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/> 
            <aop:advisor advice-ref="mythrow" pointcut-ref="mypoint" />
            <aop:advisor advice-ref="myarround" pointcut-ref="mypoint" />
        </aop:config> 
        <!-- 配置 Demo 类,测试使用 --> 
        <bean id="demo" class="com.bjsxt.test.Demo"></bean> 
    </beans>
  • AspectJ 方式

    java
    //新建类,在类写任意名称的方法
    public class MyThrowAdvice{
        public void myexception(Exception e1){ 
            System.out.println("执行异常通知 "+e1.getMessage()); 
        } 
    }
    xml
    <!--<aop:aspect>的 ref 属性表示:方法在哪个类中.-->
    <!--<aop: xxxx/> 表示什么通知-->
    <!--method: 当触发这个通知时,调用哪个方法-->
    <!--throwing: 异常对象名,必须和通知中方法参数名相同(可 以不在通知中声明异常对象)-->
    <bean id="mythrow" class="com.bjsxt.advice.MyThrowAdvice"></bean> 
    <aop:config> 
        <aop:aspect ref="mythrow">
            <aop:pointcut expression="execution(* com.bjsxt.test.Demo.demo1())" id="mypoint"/>
            <aop:after-throwing method="myexception" pointcut-ref="mypoint" throwing="e1"/>
        </aop:aspect>
    </aop:config> 
    <bean id="demo" class="com.bjsxt.test.Demo"></bean>
    
    <!--
    <aop:after/> 后置通知,是否出现异常都执行 
    <aop:after-returing/> 后置通知,只有当切点正确执行时 执行
    <aop:after/> 和 <aop:after-returing/> 和 <aop:after-throwing/>执行顺序和配置顺序有关 
    execution() 括号不能扩上 args 
    中间使用 and 不能使用&& 由 spring 把 and 解析成&& 
    args(名称) 名称自定义的.顺序和 demo1(参数,参数)对应 
    <aop:before/> arg-names=” 名 称 ” 名 称 来 源 于 expression=”” 中 args(),名称必须一样 
    args() 有几个参数,arg-names 里面必须有几个参数
    arg-names=”” 里面名称必须和通知方法参数名对应
    -->
  • Schema-based和AspectJ 方式区别

    • chema-based方式需要新建一个类并实现接口 AspectJ方式是在一个类中直接添加方法,不用实现接口
    • Schema-based配置时用的同一个标签 AspectJ不同的通知使用不同的标签
  • 注解方式(基于Aspect)

    xml
    <!-- 添加扫描注解的包路径配置 -->
    <context:component-scan base-package="com.bjsxt.advice"></context:component-scan>
    java
    // 切点配置类
    //在 切点注解类中添加@Componet
    //在方法上添加@Pointcut(“”) 定义切点
    // @Component相当于<bean/> 如果没有参数,把类名首字母变小写,相当于<bean id=""/>   @Component(“自定义名称”)
    @Component 
    public class Demo { 
        @Pointcut("execution(* com.bjsxt.test.Demo.demo1())")
        public void demo1() throws Exception{ 
            // int i = 5/0; 
            System.out.println("demo1"); 
        } 
    }
    java
    // 通知配置类
    //@Component 类被 spring 管理 
    //@Aspect 相当于<aop:aspect/>表示通知方法在当前类中
    @Component 
    @Aspect 
    public class MyAdvice { 
        @Before("com.bjsxt.test.Demo.demo1()") 
        public void mybefore(){ 
            System.out.println("前置");
        }
        @After("com.bjsxt.test.Demo.demo1()") 
        public void myafter(){ 
            System.out.println("后置通知");
        }
        @AfterThrowing("com.bjsxt.test.Demo.demo1()") 
        public void mythrow(){ 
            System.out.println("异常通知");
        }
        @Around("com.bjsxt.test.Demo.demo1()") 
        public Object myarround(ProceedingJoinPoint p) throws Throwable{ 
            System.out.println("环绕-前置");
            Object result = p.proceed(); 
            System.out.println("环绕-后置");
            return result; 
        }
    }

3.5 声明式事务

xml
<context:property-placeholder location="classpath:db.properties,classpath:second.pr operties"/> 
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverMa nagerDataSource"> 
    <property name="driverClassName" value="${jdbc.driver}">
    </property> <property name="url" value="${jdbc.url}"></property> 
    <property name="username" value="${jdbc.username}"></property> 
    <property name="password" value="${jdbc.password}"></property> 
</bean> 
<!-- spring-jdbc.jar 中 --> 
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSour ceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean> 
<!-- 配置声明式事务 -->
<tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> 
    <!-- 哪些方法需要有事务控制 --> 
    <!-- 方法以 ins 开头事务管理 --> 
    <tx:method name="ins*" />
    <tx:method name="del*" /> 
    <tx:method name="upd*" /> 
    <tx:method name="*" /> 
    </tx:attributes> 
</tx:advice> 
<aop:config> 
    <!-- 切点范围设置大一些 --> 
    <aop:pointcut expression="execution(* com.bjsxt.service.impl.*.*(..))" id="mypoint" /> 
    <aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint" /> </aop:config>

<!-- <tx:method  />中的属性解释 -- >
<!--
name:哪些方法需要有事务控制 ,支持*通配符
readonly 
	如果为 true,告诉数据库此事务为只读事务.数据化优化,会对性能有一定提升,所以只要是查询的方法,建议使用此数据如果为 
	false(默认值),事务需要提交的事务.建议新增,删除,修改
propagation:控制事务传播行为,当一个具有事务控制的方法被另一个有事务控制的方法调用后,选择如何管理事务
取值:
	REQUIRED (默认值) 如果当前有事务,就在事务中执行,如果当前没有事务,新建一个事务
	SUPPORTS 如果当前有事务就在事务中执行,如果当前没有事务,就在非事务状态下执行
	MANDATORY  必须在事务内部执行,如果当前有事务,就在事务中执行,如果没有事务,报错
	REQUIRES_NEW 必须在事务中执行,如果当前没有事务,新建事务,如果当前有事务,把当前事务挂起
	NOT_SUPPORTED 必须在非事务下执行,如果当前没有事务,正常执行,如果当前有事务,把当前事务挂起
	NEVER 必须在非事务状态下执行,如果当前没有事务,正常执行, 如果当前有事务,报错
	NESTED 必须在事务状态下执行.如果没有事务,新建事务,如果当前有事务,创建一个嵌套事务
isolation 事务隔离级别 在多线程或并发访问下如何保证访问到的数据具有完整性的
取值
	DEFAULT 默认值,由底层数据库自动判断应该使用什么隔离级别
	READ_UNCOMMITTED 可以读取未提交数据,可能出现脏读,不重复读,幻读,效率最高
	READ_COMMITTED 只能读取其他事务已提交数据.可以防止脏读,可能出现不可重复读和幻读
	REPEATABLE_READ 读取的数据被添加锁,防止其他事务修改此数据,可以防止不可重复读.脏读,可能出现幻读
	SERIALIZABLE 排队操作,对整个表添加锁.一个事务在操作数据时,另一个事务等待事务操作完成后才能操作这个表,是最安全的,也是效率最低的
rollback-for 当出现什么异常时需要进行回滚,建议给定该属性值,虽然有默认的值,取值是异常类型全限定路径.手动抛异常一定要给该属性值.
no-rollback-for 当出现什么异常时不滚回事务
 -->

3.6 代理方式&自动注入

  • 控制spring使用代理的方式

    xml
    //设置为 true 使用 cglib
    //设置为 false 使用 jdk(默认值)
    <aop:aspectj-autoproxy proxy-target-class="true">
    </aop:aspectj-autoproxy>
  • 自动注入

    在 Spring 配置文件中对象名和 ref=”id”id 名相同使用自动注入,可以 不配置<property/>
    两种配置办法 
    在<bean>中通过 autowire=”” 配置,只对这个<bean>生效 
    在<beans>中通过 default-autowire=””配置,表当当前文件中所 有<bean>都是全局配置内容 
    autowire取值:
    default: 默认值,根据全局 default-autowire=””值.默认全局和局 部都没有配置情况下,相当于 no 
    no: 不自动注入
    byName: 通过名称自动注入.在 Spring 容器中找类的 Id 
    byType: 根据类型注入.spring 容器中不可以出现两个相同类型的<bean>
    constructor: 根据构造方法注入.提供对应参数的构造方法(构造方法参数中包含注入对 戏那个) 底层使用 byName, 构造方法参数名和其他<bean>的 id 相同

3.7 加载配置文件

  1. 在 src 下新建 xxx.properties 文件

  2. 在 spring 配置文件中先引入 xmlns:context,在下面添加

    xml
    <!-- 如果需要记载多个配置文件逗号分割 ,也可使用通配符 * -->
    <context:property-placeholder location="classpath:db.properties"/>
  3. 添加了属性文件记载,并且在<beans>中开启自动注入注意的地方

    1. SqlSessionFactoryBean 的 id 不能叫做 sqlSessionFactory

    2. 把原来通过ref引用替换成value赋值,自动注入只能影响 ref,不会影响 value 赋值

      xml
      <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 
          <property name="basePackage" value="com.bjsxt.mapper"></property> 
          <property name="sqlSessionFactoryBeanName" value="factory"></property>
      </bean>
  4. 在被Spring管理的类中通过@Value(“${key}”)取出properties中内容

    xml
    <context:component-scan base-package="com.bjsxt.service.impl"></context:compo nent-scan>
    java
    //key 和变量名可以不相同
    //变量类型任意,只要保证 key 对应的 value 能转换成这个 类型就可以.
    @Value("${my.demo}") 
    private String test;

3.8 spring常用注解

java
@Component //创建类对象,相当于配置<bean/>
@Service //与@Component 功能相同.写在 ServiceImpl 类上. 
@Repository //与@Component 功能相同. 写在数据访问层类上. 
@Controller //与@Component 功能相同. 写在控制器类上. 
@Resource(不需要写对象的 get/set) //java 中的注解 默认按照 byName 注入,如果没有名称对象,按照 byType 注入 建议把对象名称和 spring 容器中对象名相同 
@Autowired(不需要写对象的 get/set) 
@Qualifier()// spring 的注解 默认按照 byType 注入. 
@Value() //获取 properties 文件中内容 
@Pointcut() //定义切点 
@Aspect() //定义切面类 
@Before() //前置通知 
@After //后置通知 
@AfterReturning //后置通知,必须切点正确执行 
@AfterThrowing //异常通知 
@Arround//环绕通知